home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr46 / vfwdk.zip / VFWSDK.ZIP / SAMPLES / MCIPLAY / MCIPLAY.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  24KB  |  593 lines

  1. /*----------------------------------------------------------------------------*\
  2.  *
  3.  *  MCIPlay
  4.  *
  5.  *    Sample app showing the use of the 'MCIWnd' window class
  6.  *
  7.  *    the MCIWnd window class is a window class for controling MCI devices
  8.  *    MCI devices include, wave files, midi files, AVI Video, cd audio,
  9.  *    vcr, video disc, and others..
  10.  *
  11.  *    the easiest use of the MCIWnd class is like so:
  12.  *
  13.  *          hwnd = MCIWndCreate(hwndParent, hInstance, 0, "smag.wav");
  14.  *          ...
  15.  *          MCIWndPlay(hwnd);
  16.  *          ....
  17.  *          MCIWndDestroy(hwnd);
  18.  *
  19.  *    this will create a window with a play/pause, stop and a playbar
  20.  *    and start the wave file playing.
  21.  *
  22.  *    mciwnd.h defines macros for all the most common MCI commands, but
  23.  *    any string command can be used if needed.
  24.  *
  25.  *          MCIWndSendString(hwnd, "set hue to bright");
  26.  *
  27.  *
  28.  *    most of this app deals with the overhead of MDI, the real work happens
  29.  *    mostly on WM_COMMAND (look for MCIWnd for real code)
  30.  *
  31.  *        case IDM_PLAY:
  32.  *            MCIWndPlay(hwndMovie);
  33.  *            break;
  34.  *
  35.  *    this MDI app handles palettes by letting the topmost MDI child take
  36.  *    control of the palette, all others paint in the background.  what
  37.  *    realy happens is the WM_QUERYNEWPALETTE message is only sent to
  38.  *    the top most MDI window.
  39.  *
  40.  *    In order to open a non-file device (like CDAUDIO) with this sample
  41.  *    application, you will need to launch it from the command line (eg.
  42.  *    "mciplay cdaudio" since the file open dialog will not let you type in
  43.  *    the device name if it does not exist as a filename on your drive.
  44.  *
  45.  *    (C) Copyright Microsoft Corp. 1991, 1992, 1993.  All rights reserved.
  46.  *
  47.  *    You have a royalty-free right to use, modify, reproduce and
  48.  *    distribute the Sample Files (and/or any modified version) in
  49.  *    any way you find useful, provided that you agree that
  50.  *    Microsoft has no warranty obligations or liability for any
  51.  *    Sample Application Files.
  52.  *
  53.  *    If you did not get this from Microsoft Sources, then it may not be the
  54.  *    most current version.  This sample code in particular will be updated
  55.  *    and include more documentation.
  56.  *
  57.  *    Sources are:
  58.  *       CompuServe: WINSDK forum, MDK section.
  59.  *       Anonymous FTP from ftp.uu.net vendor\microsoft\multimedia
  60.  *
  61.  *----------------------------------------------------------------------------*/
  62.  
  63. #include <windows.h>
  64. #include <commdlg.h>
  65. #include "mciwnd.h"
  66.  
  67. #include "mciplay.h"
  68.  
  69. //
  70. // constants
  71. //
  72. #define ACH_BUFFER_LENGTH   128
  73.  
  74.  
  75. /*-------------------------------------------------------------------------*\
  76. |                                                                          |
  77. |   g l o b a l   v a r i a b l e s                                        |
  78. |                                                                          |
  79. \*------------------------------------------------------------------------*/
  80.  
  81. char    szAppName[]  = "MCIPlay";   /* change this to your app's name */
  82. char    szDocClass[] = MCIWND_WINDOW_CLASS;
  83.  
  84. char    szOpenFilter[] = "Video Files\0*.avi\0"
  85.                          "Wave Files\0*.wav\0"
  86.                          "Midi Files\0*.mid; *.rmi\0"
  87.                          "All Files\0*.*\0";
  88.  
  89. HANDLE  hInstApp;                   /* Instance handle */
  90. HACCEL  hAccelApp;
  91. HWND    hwndApp;                    /* Handle to parent window */
  92. HWND    hwndMdi;                    /* Handle to MCI client window */
  93.  
  94. OFSTRUCT     of;
  95. OPENFILENAME ofn;
  96. char         achFileName[ACH_BUFFER_LENGTH];
  97.  
  98. /*----------------------------------------------------------------------------*\
  99. \*----------------------------------------------------------------------------*/
  100.  
  101. long FAR PASCAL _export AppWndProc(HWND, UINT, WPARAM, LPARAM);
  102. int ErrMsg (LPSTR sz,...);
  103.  
  104. HWND mdiCreateDoc(LPSTR szClass, LPSTR szTitle, LPARAM l);
  105.  
  106. /*----------------------------------------------------------------------------*\
  107. |   AppAbout( hDlg, msg, wParam, lParam )                                      |
  108. |                                                                              |
  109. |   Description:                                                               |
  110. |       This function handles messages belonging to the "About" dialog box.    |
  111. |       The only message that it looks for is WM_COMMAND, indicating the use   |
  112. |       has pressed the "OK" button.  When this happens, it takes down         |
  113. |       the dialog box.                                                        |
  114. |                                                                              |
  115. |   Arguments:                                                                 |
  116. |       hDlg            window handle of about dialog window                   |
  117. |       msg             message number                                         |
  118. |       wParam          message-dependent                                      |
  119. |       lParam          message-dependent                                      |
  120. |                                                                              |
  121. |   Returns:                                                                   |
  122. |       TRUE if message has been processed, else FALSE                         |
  123. |                                                                              |
  124. \*----------------------------------------------------------------------------*/
  125. BOOL FAR PASCAL _export AppAbout(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  126. {
  127.     switch (msg) {
  128.         case WM_COMMAND:
  129.             EndDialog(hwnd,TRUE);
  130.             return TRUE;
  131.  
  132.         case WM_INITDIALOG:
  133.         return TRUE;
  134.     }
  135.     return FALSE;
  136. }
  137.  
  138. /*----------------------------------------------------------------------------*\
  139. |   AppInit ( hInstance, hPrevInstance )                       |
  140. |                                                                              |
  141. |   Description:                                                               |
  142. |       This is called when the application is first loaded into               |
  143. |       memory.  It performs all initialization that doesn't need to be done   |
  144. |       once per instance.                                                     |
  145. |                                                                              |
  146. |   Arguments:                                                                 |
  147. |    hPrevInstance    instance handle of previous instance               |
  148. |       hInstance       instance handle of current instance                    |
  149. |                                                                              |
  150. |   Returns:                                                                   |
  151. |       TRUE if successful, FALSE if not                                       |
  152. |                                                                              |
  153. \*----------------------------------------------------------------------------*/
  154. BOOL AppInit(HANDLE hInst, HANDLE hPrev, LPSTR szCmd, int sw)
  155. {
  156.     WNDCLASS    cls;
  157.  
  158.     /* Save instance handle for DialogBox */
  159.     hInstApp = hInst;
  160.  
  161.     hAccelApp = LoadAccelerators(hInstApp, "AppAccel");
  162.  
  163.     if (!hPrev) {
  164.         cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  165.         cls.hIcon          = LoadIcon(hInst,"AppIcon");
  166.         cls.lpszMenuName   = "AppMenu";
  167.         cls.lpszClassName  = szAppName;
  168.         cls.hbrBackground  = (HBRUSH)COLOR_APPWORKSPACE+1;
  169.         cls.hInstance      = hInst;
  170.         cls.style          = 0;
  171.         cls.lpfnWndProc    = (WNDPROC)AppWndProc;
  172.         cls.cbClsExtra     = 0;
  173.     cls.cbWndExtra       = 0;
  174.  
  175.         if (!RegisterClass(&cls))
  176.             return FALSE;
  177.     }
  178.  
  179.     //
  180.     // because this app uses CreateWindow() to make 'MCIWnd' windows
  181.     // we need to register the window class by hand, if you use MCIWndCreate()
  182.     // you dont need to do this.
  183.     //
  184.     MCIWndRegisterClass(hInst);
  185.  
  186.     hwndApp = CreateWindow(szAppName,szAppName,
  187.            WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  188.            CW_USEDEFAULT,0,
  189.            CW_USEDEFAULT,0,
  190.            (HWND)NULL,      /* no parent */
  191.            (HMENU)NULL,      /* use class menu */
  192.                (HANDLE)hInst,     /* handle to window instance */
  193.            (LPSTR)NULL      /* no params to pass on */
  194.          );
  195.  
  196.     /* Make window visible according to the way the app is activated */
  197.     ShowWindow(hwndApp,sw);
  198.  
  199.     if (szCmd && szCmd[0])
  200.         mdiCreateDoc(szDocClass, szCmd, 0);
  201.  
  202.     return TRUE;
  203. }
  204.  
  205. /*----------------------------------------------------------------------------*\
  206. |   WinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow )                  |
  207. |                                                                              |
  208. |   Description:                                                               |
  209. |       The main procedure for the App.  After initializing, it just goes      |
  210. |       into a message-processing loop until it gets a WM_QUIT message         |
  211. |       (meaning the app was closed).                                          |
  212. |                                                                              |
  213. |   Arguments:                                                                 |
  214. |       hInstance       instance handle of this instance of the app            |
  215. |       hPrevInstance   instance handle of previous instance, NULL if first    |
  216. |       lpszCmdLine     ->null-terminated command line                         |
  217. |       cmdShow         specifies how the window is initially displayed        |
  218. |                                                                              |
  219. |   Returns:                                                                   |
  220. |       The exit code as specified in the WM_QUIT message.                     |
  221. |                                                                              |
  222. \*----------------------------------------------------------------------------*/
  223. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int sw)
  224. {
  225.     MSG     msg;
  226.  
  227.     if (!AppInit(hInstance,hPrevInstance,szCmdLine,sw))
  228.        return FALSE;
  229.  
  230.     /*
  231.      * Polling messages from event queue
  232.      */
  233.     for (;;)
  234.     {
  235.         if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
  236.         {
  237.             if (msg.message == WM_QUIT)
  238.                 break;
  239.  
  240.             if (hAccelApp && TranslateAccelerator(hwndApp, hAccelApp, &msg))
  241.                 continue;
  242.  
  243.             TranslateMessage(&msg);
  244.             DispatchMessage(&msg);
  245.         }
  246.         else
  247.         {
  248.             // idle time here, DONT BE A PIG!
  249.             WaitMessage();
  250.         }
  251.     }
  252.  
  253.     return msg.wParam;
  254. }
  255.  
  256. /*----------------------------------------------------------------------------*\
  257. \*----------------------------------------------------------------------------*/
  258.  
  259. BOOL fDialog(HWND hwnd,int id,FARPROC fpfn)
  260. {
  261.     BOOL    f;
  262.     HANDLE    hInst;
  263.  
  264.     hInst = (HINSTANCE)GetWindowWord(hwnd,GWW_HINSTANCE);
  265.     fpfn  = MakeProcInstance(fpfn,hInst);
  266.     f = DialogBox(hInst,MAKEINTRESOURCE(id),hwnd,(DLGPROC)fpfn);
  267.     FreeProcInstance (fpfn);
  268.     return f;
  269. }
  270.  
  271. /*----------------------------------------------------------------------------*\
  272. \*----------------------------------------------------------------------------*/
  273.  
  274. #define mdiGetCreateParam(lParam) \
  275.     (((LPMDICREATESTRUCT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->lParam)
  276.  
  277. /*----------------------------------------------------------------------------*\
  278. |   mdiCreateChild()                                   |
  279. |                                           |
  280. |   Description:                                                               |
  281. |                                                                              |
  282. |   Arguments:                                                                 |
  283. |                                                                              |
  284. |   Returns:                                                                   |
  285. |    HWND if successful, NULL otherwise                       |
  286. |                                           |
  287. \*----------------------------------------------------------------------------*/
  288.  
  289. HWND mdiCreateChild(
  290.     HWND  hwndMdi,
  291.     LPSTR szClass,
  292.     LPSTR szTitle,
  293.     DWORD dwStyle,
  294.     int   x,
  295.     int   y,
  296.     int   dx,
  297.     int   dy,
  298.     WORD  sw,
  299.     HMENU hmenu,
  300.     LPARAM l)
  301. {
  302.     //
  303.     //    this is where we create a MCIWnd, by default a MCIWnd will try to
  304.     //    open it's window text as a filename or device.
  305.     //
  306.     //    so the window text is the file name.
  307.     //
  308.     //    another way to open a file/device is to use MCIWndOpen()
  309.     //
  310.     //        hwnd = MCIWndCreate(hwndParent, hInstance, 0, "");
  311.     //        MCIWndOpen(hwnd, "cdaudio", 0);
  312.     //
  313.  
  314.     MDICREATESTRUCT mdics;
  315.  
  316.     mdics.szClass   = szClass;
  317.     mdics.szTitle   = szTitle;
  318.     mdics.hOwner    = (HINSTANCE)GetWindowWord(hwndMdi, GWW_HINSTANCE);
  319.     mdics.x         = x;
  320.     mdics.y         = y;
  321.     mdics.cx        = dx;
  322.     mdics.cy        = dy;
  323.     mdics.style     = dwStyle;
  324.     mdics.lParam    = l;
  325.  
  326.     return (HWND)SendMessage(hwndMdi,WM_MDICREATE,0,(LONG)(LPVOID)&mdics);
  327. }
  328.  
  329. /*----------------------------------------------------------------------------*\
  330. \*----------------------------------------------------------------------------*/
  331.  
  332. HWND mdiCreateDoc(LPSTR szClass, LPSTR szTitle, LPARAM l)
  333. {
  334.     return mdiCreateChild(hwndMdi,szClass,szTitle,
  335.     WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  336.         CW_USEDEFAULT,0,CW_USEDEFAULT,0,SW_NORMAL,NULL,l);
  337. }
  338.  
  339. /*----------------------------------------------------------------------------*\
  340. |   mdiCreateClient()                                                           |
  341. |                                           |
  342. |   Description:                                                               |
  343. |                                                                              |
  344. |   Arguments:                                                                 |
  345. |                                                                              |
  346. |   Returns:                                                                   |
  347. |    HWND if successful, NULL otherwise                       |
  348. |                                           |
  349. \*----------------------------------------------------------------------------*/
  350. HWND FAR PASCAL mdiCreateClient(HWND hwndP, HMENU hmenuWindow)
  351. {
  352.     CLIENTCREATESTRUCT ccs;
  353.  
  354.     ccs.hWindowMenu = hmenuWindow;
  355.     ccs.idFirstChild = 942;
  356.  
  357.     return CreateWindow ("MDICLIENT",NULL,
  358.                 WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
  359.                 0,0,0,0,
  360.                 hwndP, 0, (HINSTANCE)GetWindowWord(hwndP,GWW_HINSTANCE),
  361.                 (LPVOID)&ccs);
  362. }
  363.  
  364. /*----------------------------------------------------------------------------*\
  365. \*----------------------------------------------------------------------------*/
  366.  
  367. #define mdiActiveDoc() \
  368.     (HWND)SendMessage(hwndMdi,WM_MDIGETACTIVE,0,0L)
  369.  
  370. /*----------------------------------------------------------------------------*\
  371. \*----------------------------------------------------------------------------*/
  372.  
  373. LONG NEAR PASCAL mdiSendMessage(HWND hwndMdi, HWND hwnd, unsigned msg, WORD wParam, LONG lParam)
  374. {
  375.     if (hwnd == (HWND)-1)
  376.     {
  377.         for (hwnd = GetWindow(hwndMdi, GW_CHILD); hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT))
  378.             SendMessage(hwnd, msg, wParam, lParam);
  379.  
  380.         return 0L;
  381.     }
  382.     else
  383.     {
  384.         if (hwnd == NULL)
  385.             hwnd = (HWND)SendMessage(hwndMdi,WM_MDIGETACTIVE,0,0L);
  386.  
  387.         if (hwnd)
  388.             return SendMessage(hwnd, msg, wParam, lParam);
  389.     }
  390. }
  391.  
  392. /*----------------------------------------------------------------------------*\
  393. |   AppWndProc( hwnd, msg, wParam, lParam )                                    |
  394. |                                                                              |
  395. |   Description:                                                               |
  396. |       The window proc for the app's main (tiled) window.  This processes all |
  397. |       of the parent window's messages.                                       |
  398. |                                           |
  399. |   Arguments:                                                                 |
  400. |       hwnd            window handle for the parent window                    |
  401. |       msg             message number                                         |
  402. |       wParam          message-dependent                                      |
  403. |       lParam          message-dependent                                      |
  404. |                                                                              |
  405. |   Returns:                                                                   |
  406. |       0 if processed, nonzero if ignored                                     |
  407. |                                                                              |
  408. \*----------------------------------------------------------------------------*/
  409. long FAR PASCAL _export AppWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
  410. {
  411.     UINT            f;
  412.     PAINTSTRUCT     ps;
  413.     HDC             hdc;
  414.     HMENU           hmenu;
  415.     HWND            hwndMovie;
  416.     HWND            hwndT;
  417.  
  418.     switch (msg) {
  419.         case WM_COMMAND:
  420.             hwndMovie = mdiActiveDoc();
  421.  
  422.         switch(wParam) {
  423.         case MENU_ABOUT:
  424.                     fDialog(hwnd,ABOUTBOX,(FARPROC)AppAbout);
  425.             break;
  426.  
  427.         case MENU_EXIT:
  428.                     PostMessage(hwnd,WM_CLOSE,0,0L);
  429.                     break;
  430.  
  431.                 case MENU_CLOSE:
  432.                     SendMessage(hwndMovie,WM_CLOSE,0,0);
  433.                     break;
  434.  
  435.                 case MENU_CLOSEALL:
  436.                     while (hwndT = mdiActiveDoc())
  437.             SendMessage(hwndT,WM_CLOSE,0,0);
  438.                     break;
  439.  
  440.                 case MENU_NEW:
  441.                     mdiCreateDoc(szDocClass, "Untitled", 0);
  442.                     break;
  443.  
  444.                 case MENU_OPEN:
  445.                     /* prompt user for file to open */
  446.                     ofn.lStructSize = sizeof(OPENFILENAME);
  447.                     ofn.hwndOwner = hwnd;
  448.                     ofn.hInstance = NULL;
  449.                     ofn.lpstrFilter = szOpenFilter;
  450.                     ofn.lpstrCustomFilter = NULL;
  451.                     ofn.nMaxCustFilter = 0;
  452.                     ofn.nFilterIndex = 0;
  453.                     ofn.lpstrFile = achFileName;
  454.                     ofn.nMaxFile = sizeof(achFileName);
  455.                     ofn.lpstrFileTitle = NULL;
  456.                     ofn.nMaxFileTitle = 0;
  457.                     ofn.lpstrInitialDir = NULL;
  458.                     ofn.lpstrTitle = "Open";
  459.                     ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  460.                     ofn.nFileOffset = 0;
  461.                     ofn.nFileExtension = 0;
  462.                     ofn.lpstrDefExt = NULL;
  463.                     ofn.lCustData = 0;
  464.                     ofn.lpfnHook = NULL;
  465.                     ofn.lpTemplateName = NULL;
  466.  
  467.                     if (GetOpenFileName(&ofn))
  468.                     {
  469.                         hwndMovie = mdiCreateDoc(szDocClass, achFileName, 0);
  470.                         if (hwndMovie) {
  471.                             char  achFileTitle[ACH_BUFFER_LENGTH];
  472.                     //
  473.                     // Set the window text to the filename without the
  474.                     // directory path information.
  475.                     //
  476.                             GetFileTitle(achFileName,
  477.                                          achFileTitle,
  478.                                          ACH_BUFFER_LENGTH);
  479.                             SetWindowText(hwndMovie,achFileTitle);
  480.                         }
  481.                     }
  482.                     break;
  483.  
  484.                 case WM_MDITILE:
  485.                 case WM_MDICASCADE:
  486.                 case WM_MDIICONARRANGE:
  487.                     SendMessage(hwndMdi, (UINT)wParam, 0, 0);
  488.                     break;
  489.  
  490.                 /* Movie Menu */
  491.                 case IDM_PLAY:
  492.                     MCIWndPlay(hwndMovie);
  493.                     break;
  494.                 case IDM_RPLAY:
  495.                     MCIWndPlayReverse(hwndMovie);
  496.                     break;
  497.                 case IDM_STOP:
  498.                     MCIWndStop(hwndMovie);
  499.                     break;
  500.                 case IDM_HOME:
  501.                     MCIWndHome(hwndMovie);
  502.                     break;
  503.                 case IDM_END:
  504.                     MCIWndEnd(hwndMovie);
  505.                     break;
  506.                 case IDM_STEP:
  507.                     MCIWndStep(hwndMovie, 1);
  508.                     break;
  509.                 case IDM_RSTEP:
  510.                     MCIWndStep(hwndMovie, -1);
  511.                     break;
  512.                 default:
  513.                     mdiSendMessage(hwndMdi,NULL,msg,wParam,lParam);
  514.                     break;
  515.         }
  516.             break;
  517.  
  518.         case WM_PALETTECHANGED:
  519.             mdiSendMessage(hwndMdi, (HWND)-1, msg, wParam, lParam);
  520.             break;
  521.  
  522.         case WM_QUERYNEWPALETTE:
  523.             return mdiSendMessage(hwndMdi, NULL, msg, wParam, lParam);
  524.  
  525.         case WM_INITMENU:
  526.             hwndMovie = mdiActiveDoc();
  527.  
  528.             if (!hwndMovie || MCIWndGetMode(hwndMovie) == MCI_MODE_NOT_READY) {
  529.         f = hwndMovie ? MF_ENABLED : MF_GRAYED;
  530.                 EnableMenuItem((HMENU)wParam, MENU_CLOSE, f);
  531.                 EnableMenuItem((HMENU)wParam, MENU_CLOSEALL, f);
  532.  
  533.                 EnableMenuItem((HMENU)wParam, IDM_STOP, MF_GRAYED);
  534.                 EnableMenuItem((HMENU)wParam, IDM_PLAY, MF_GRAYED);
  535.                 EnableMenuItem((HMENU)wParam, IDM_RPLAY, MF_GRAYED);
  536.                 EnableMenuItem((HMENU)wParam, IDM_HOME, MF_GRAYED);
  537.                 EnableMenuItem((HMENU)wParam, IDM_END, MF_GRAYED);
  538.                 EnableMenuItem((HMENU)wParam, IDM_STEP, MF_GRAYED);
  539.                 EnableMenuItem((HMENU)wParam, IDM_RSTEP, MF_GRAYED);
  540.             }
  541.             else {
  542.                 EnableMenuItem((HMENU)wParam, MENU_CLOSE, MF_ENABLED);
  543.                 EnableMenuItem((HMENU)wParam, MENU_CLOSEALL, MF_ENABLED);
  544.  
  545.                 f = MCIWndGetMode(hwndMovie) != MCI_MODE_STOP;
  546.                 EnableMenuItem((HMENU)wParam, IDM_PLAY, !f ? MF_ENABLED : MF_GRAYED);
  547.                 EnableMenuItem((HMENU)wParam, IDM_RPLAY,!f ? MF_ENABLED : MF_GRAYED);
  548.                 EnableMenuItem((HMENU)wParam, IDM_STOP, f  ? MF_ENABLED : MF_GRAYED);
  549.  
  550.                 EnableMenuItem((HMENU)wParam, IDM_HOME, MF_ENABLED);
  551.                 EnableMenuItem((HMENU)wParam, IDM_END,  MF_ENABLED);
  552.                 EnableMenuItem((HMENU)wParam, IDM_STEP, MF_ENABLED);
  553.                 EnableMenuItem((HMENU)wParam, IDM_RSTEP,MF_ENABLED);
  554.             }
  555.  
  556.             return mdiSendMessage(hwndMdi, NULL, msg, wParam, lParam);
  557.             break;
  558.  
  559.        case WM_CREATE:
  560.             hmenu = GetMenu(hwnd);
  561.             hwndMdi = mdiCreateClient(hwnd, GetSubMenu(hmenu, GetMenuItemCount(hmenu)-1));
  562.             break;
  563.  
  564.        case WM_SIZE:
  565.             MoveWindow(hwndMdi,0,0,LOWORD(lParam),HIWORD(lParam),TRUE);
  566.             break;
  567.  
  568.        case WM_DESTROY:
  569.         PostQuitMessage(0);
  570.         break;
  571.  
  572.        case WM_PAINT:
  573.             hdc = BeginPaint(hwnd, &ps);
  574.             EndPaint(hwnd, &ps);
  575.             return 0;
  576.     }
  577.     return DefFrameProc(hwnd,hwndMdi,msg,wParam,lParam);
  578. }
  579.  
  580. /*----------------------------------------------------------------------------*\
  581. |   ErrMsg - Opens a Message box with a error message in it.  The user can     |
  582. |         select the OK button to continue or the CANCEL button to kill     |
  583. |         the parent application.                           |
  584. \*----------------------------------------------------------------------------*/
  585. int ErrMsg (LPSTR sz,...)
  586. {
  587.     char ach[ACH_BUFFER_LENGTH];
  588.  
  589.     wvsprintf(ach,sz,(LPSTR)(&sz+1));   /* Format the string */
  590.     MessageBox (NULL,ach,NULL,MB_OK|MB_ICONEXCLAMATION);
  591.     return FALSE;
  592. }
  593.